#include "stdafx.h"
#include "XModem.h"
#include "Uart.h"
#include "Utils.h"
#include <string.h>
#include <unistd.h>
#include "VanException.h"

XModem* XModem::m_pInstance = NULL;

XModem::XModem()
{
m_State = 0;
}

XModem::~XModem()
{
m_State = 2;
}

XModem* XModem::Instance()
{
	if (NULL == m_pInstance) {
		m_pInstance = new XModem();
	}

	return m_pInstance;
}

void XModem::OnChar()
{
	if (m_State) {

	}
	switch (m_State)
	{
	case 0:
		m_State = 1;
		break;
	default:
		break;
	}
}

bool XModem::SendFile(const char* path)
{
if (!m_Request.Open()) {
	return false;
	}

	for (int i = 0; i < 10; ++i) {
	if (1 == m_State) {
			break;
	}

	usleep(200000);
	}

	if (1 != m_State) {
	m_State = 0;
	m_Request.Close();
	return false;
	}

	SendD(path);
	bool bRet = SendF();
	m_State = 0;

	m_Request.Close();
	return true;
}

bool XModem::SendD(const char* path)
{
	FILE* file = fopen(path, "rb");
	if (NULL == file) {
	return false;
	}

	fseek(file, 0, 2);
	long file_size = ftell(file);
	fseek(file, 0, 0);

	int nB = file_size / 1024;
	byte buf[3000];
	bool bRet = true;

	for (int i = 0; i < nB; ++i)
	{
	memset(buf, 0, sizeof(buf));
	buf[0] = 2;
	buf[1] = (byte)((i + 1) & 0xFF);
	buf[2] = (byte)(~buf[1]);

	fread(buf + 3, 1024, 1, file);

	int cr = check(buf + 3, 1024);
	buf[1027] = (byte)(cr >> 8);
	buf[1028] = (byte)(cr & 0xFF);


			bRet = m_Request.Request(buf, 1029);

			if (!bRet) {
				fclose(file);
				return bRet;
			}

	}

	int size = file_size % 1024;

	if (size > 0)
	{
	memset(buf, 0, sizeof(buf));
	buf[0] = 2;
	buf[1] = (byte)((nB + 1) & 0xFF);
	buf[2] = (byte)(~buf[1]);

	fread(buf + 3, 1024, 1, file);

	int cr = check(buf + 3, 1024);
	buf[1027] = (byte)(cr >> 8);
	buf[1028] = (byte)(cr & 0xFF);

			bRet = m_Request.Request(buf, 1029);

	}

	fclose(file);
	return bRet;
}

bool XModem::SendF()
{
	byte data = 4;
	bool bRet;
bRet = m_Request.Request(&data, 1, false);


	return bRet;
}

int XModem::check(const byte* pBuf, int lenght)
{
int cr = 0;

while (--lenght >=0)
	{
	cr ^= (*pBuf++ << 8);

	for (int i = 0; i < 8; ++i)
		{
			if (cr & 0x8000) {
				cr = (cr << 1) ^ 0x1021;
			} else {
				cr <<= 1;
			}
		}
	}

return (cr & 0xFFFF);
}
